<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>K-means clustering visualization for ab initio materials data</title>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<style>
body{margin:0;padding:0;overflow:hidden;}
html, body{height:100%;}
#plot3d{width:100%;height:100%;}
</style>
<script type="text/javascript" src="../static/js/plotly.min.js"></script>
</head>
<body>
<div id="plot3d"></div>
<script type="text/javascript">
var points = {}, clusters = [], total_downloads = 2, colors = ['#396', '#06f', '#9c6', '#6cf', '#f90', '#90c', '#f00', '#300', '#fc6', '#c00'];

function unpack(rows, key, verbatim){
    if (verbatim) return rows.map(function(row) { return row[key] });
    else return rows.map(function(row) { return parseFloat(row[key]) });
}

function shake(rows){
    return rows.map(function(row) { return row + ((Math.random() < 0.5) ? -0.1 : 0.1) });
}

function gen_shake(){
    return Math.floor(Math.random()*25) * ((Math.floor(Math.random()*2) == 1) ? 0.01 : -0.01);
}

Plotly.d3.csv('../static/points.csv', function(err, rows){
    window.points = {
        x: unpack(rows, 'x'),
        y: unpack(rows, 'y'),
        z: unpack(rows, 'z'),
        text: unpack(rows, 'label', true),
        mode: 'markers',
        type: 'scatter3d',
        hoverinfo: 'text',
        marker: {
        color: '#f00',
        size: 3}
    }
    if (!--total_downloads) render_all();
});

Plotly.d3.csv('../static/clusters.csv', function(err, rows){
    var container = [], cnt = 0;
    for (var i=0; i<rows.length; i++){
        if (rows[i].x=="-" && rows[i].y=="-" && rows[i].z=="-"){
            // for too small clusters
            if (container.length < 5){
                for (var j=0, todo=5-container.length; j<todo; j++){
                    container.push({
                        x:parseFloat(container[0].x)+gen_shake(),
                        y:parseFloat(container[0].y)+gen_shake(),
                        z:parseFloat(container[0].z)+gen_shake()
                    });
                }
            }
            window.clusters.push({
                type: 'mesh3d',
                alphahull: 1,
                x: shake(unpack(container, 'x')),
                y: shake(unpack(container, 'y')),
                z: unpack(container, 'z'),
                opacity: 0.075,
                color: window.colors[cnt] || '#000',
                hoverinfo: 'none'
            });
            container = [];
            cnt++;
        } else container.push(rows[i]);
    }
    if (!--total_downloads) render_all();
});

function render_all(){
var layout = {
    autosize: true,
    width: document.body.clientWidth,
    height: document.body.clientHeight,
    scene: {
        aspectratio: {
        x: 1,
        y: 1,
        z: 1
        },
        camera: {
        center: {
        x: 0,
        y: 0,
        z: 0
        },
        eye: {
        x: 1.25,
        y: 1.25,
        z: 1.25
        },
        up: {
        x: 0,
        y: 0,
        z: 1
        }
        },
        xaxis: {
        title: 'Group',
        dtick: 1.0,
        type: 'linear',
        zeroline: false
        },
        yaxis: {
        title: 'Group',
        dtick: 1.0,
        type: 'linear',
        zeroline: false
        },
        zaxis: {
        title: 'Band gap, eV',
        type: 'linear',
        zeroline: false
        }
    }
}
var data = [window.points];
//console.log(window.clusters);
for (var i=0; i<window.clusters.length; i++){
    data.push(window.clusters[i]);
}

Plotly.newPlot('plot3d', data, layout);
}
</script>
</body>
</html>
